package com.xiaojiezhu.netty.base.protocol;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.util.CharsetUtil;

import java.util.List;

/**
 * 作者 zxj<br>
 * 时间 2017/7/14 16:40
 * 说明 ...
 */
public class CobraDecoder extends ByteToMessageDecoder {
    /**
     * <pre>
     * 协议的开始长度:
     * 协议开始的标志，int 4个字节
     * 协议中内容的长度,int 4个字节
     * 协议中的content-type为256个字节
     * </pre>
     */
    public final static int BASE_LENGTH = 4 + 4 + CobraProtocolHeader.CONTENT_TYPE_LENGTH;

    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        if(in.readableBytes() >= BASE_LENGTH){
            //判断流量太大，防止socket攻击 ...
            //....补充....

            int beginReader;
            while (true){
                //获取包开头的index
                beginReader = in.readerIndex();
                //标记包开头的Index
                in.markReaderIndex();
                //读取协议开头，结束循环
                if(in.readInt() == CobraProtocol.HEAD_DATA){
                    break;
                }

                //未读取包头，略过一个字节
                in.resetReaderIndex();
                // 每次略过，一个字节，去读取，包头信息的开始标记
                in.readByte();

                // 当略过，一个字节之后，
                // 数据包的长度，又变得不满足
                // 此时，应该结束。等待后面的数据到达
                if (in.readableBytes() < BASE_LENGTH) {
                    return;
                }
            }

            //获取content-type
            String contentType = ((String) in.readCharSequence(CobraProtocolHeader.CONTENT_TYPE_LENGTH, CharsetUtil.UTF_8)).trim();
            //消息的长度
            int contentLength = in.readInt();
            //判断请求包数据是否到齐
            if(in.readableBytes() < contentLength){
                //还原读指针
                in.readerIndex(beginReader);
                return;
            }


            //读取data数据
            byte[] bytes = new byte[contentLength];
            in.readBytes(bytes);

            CobraProtocol cobraProtocol = new CobraProtocol(contentType,bytes);
            out.add(cobraProtocol);
        }
    }
}
